---
layout: docs
page_title: gateway block in the job specification
description: |-
  Configure a Consul mesh, ingress, or terminating gateway in the `gateway` block of the Nomad job specification.
---

# `gateway` block in the job specification

<Placement groups={['job', 'group', 'service', 'connect', 'gateway']} />

The `gateway` block allows configuration of [Consul service mesh gateways](/consul/docs/connect/gateways). Nomad will automatically create the
necessary Gateway [Configuration Entry](/consul/docs/agent/config-entries) as
well as inject an Envoy proxy task into the Nomad job to serve as the Gateway.

The `gateway` configuration is valid within the context of a `connect` block.
Additional information about Gateway configurations can be found in Consul's
[Connect Gateways](/consul/docs/connect/gateways) documentation.

~> **Note:** [Ingress Gateways](/consul/docs/connect/gateways/ingress-gateway)
are generally intended for enabling access into a Consul service mesh from within the
same network. For public ingress products like [NGINX](/nomad/tutorials/load-balancing/load-balancing-nginx)
provide more suitable features.

```hcl
service {
  connect {
    gateway {
      # ...
    }
  }
}
```

## Parameters

Exactly one of `ingress`, `terminating`, or `mesh` must be configured.

- `proxy` <code>([proxy]: nil)</code> - Configuration of the Envoy proxy that will
  be injected into the task group.
- `ingress` <code>([ingress]: nil)</code> - Configuration Entry of type `ingress-gateway`
  that will be associated with the service.
- `terminating` <code>([terminating]: nil)</code> - Configuration Entry of type `terminating-gateway`
  that will be associated with the service.
- `mesh` <code>([mesh]: nil)</code> - Indicates a mesh gateway will be associated
  with the service.

### `proxy` parameters

- `connect_timeout` `(string: "5s")` - The amount of time to allow when making
  upstream connections before timing out. Defaults to 5 seconds. If the upstream
  service has the configuration option <code>[connect_timeout_ms]</code> set for
  the `service-resolver`, that timeout value will take precedence over this
  gateway proxy option.

- `envoy_gateway_bind_tagged_addresses` `(bool: false)` - Indicates that the
  gateway services tagged addresses should be bound to listeners in addition to
  the default listener address.

- `envoy_gateway_bind_addresses` <code>(map<string|[address]>: nil)</code> - A
  map of additional addresses to be bound.  The keys to this map are the same of
  the listeners to be created and the values are a map with two keys - address
  and port, that combined make the address to bind the listener to. These are
  bound in addition to the default address.  If `bridge` networking is in use,
  this map is automatically populated with additional listeners enabling the
  Envoy proxy to work from inside the network namespace.

  ```hcl
  envoy_gateway_bind_addresses "<service>" {
    address = "0.0.0.0"
    port    = <port>
  }
  ```

- `envoy_gateway_no_default_bind` `(bool: false)` - Prevents binding to the default
  address of the gateway service. This should be used with one of the other options
  to configure the gateway's bind addresses. If `bridge` networking is in use, this
  value will default to `true` since the Envoy proxy does not need to bind to the
  service address from inside the network namespace.
- `envoy_dns_discovery_type` `(string: optional)` - Determintes how Envoy will
  resolve hostnames. Defaults to `LOGICAL_DNS`. Must be one of `STRICT_DNS` or
  `LOGICAL_DNS`. Details for each type are available in the [Envoy
  Documentation][envoy_sd_docs].  This option applies to terminating gateways
  that route to services addressed by a hostname.
- `config` `(map: nil)` - Escape hatch for [Advanced Configuration] of Envoy.
  Keys and values support [runtime variable interpolation][interpolation].

#### `address` parameters

- `address` `(string: required)` - The address to bind to when combined with `port`.
- `port` `(int: required)` - The port to listen to.

### `ingress` parameters

- `listener` <code>(array<[listener]> : required)</code> - One or more listeners
  that the ingress gateway should setup, uniquely identified by their port
  number.

- `tls` <code>([tls]: nil)</code> - TLS configuration for this gateway.

#### `listener` parameters

- `port` `(int: required)` - The port that the listener should receive traffic on.

- `protocol` `(string: "tcp")` - The protocol associated with the listener. One
  of `tcp`, `http`, `http2`, or `grpc`.

  ~> **Note:** If using any protocol other than `tcp` (for example: `http` or
  `grpc`), preconfiguring a [service-default][] in Consul to set the
  [Protocol][service-default-protocol] of the service to the desired protocol is
  mandatory due to an [open issue](https://github.com/hashicorp/nomad/issues/8647).

- `service` <code>(array<[listener-service]>: required)</code> - One or more services to be
  exposed via this listener. For `tcp` listeners, only a single service is allowed.

#### Listener `service` parameters

The `service` blocks for a listener under an `ingress` gateway accept the
following parameters. Note these are different than the `service` blocks under a
`terminating` gateway.

- `name` `(string: required)` - The name of the service that should be exposed through
  this listener. This can be either a service registered in the catalog, or a
  service defined by other config entries, or a service that is going to be configured
  by Nomad. If the wildcard specifier `*` is provided, then ALL services will be
  exposed through this listener. This is not supported for a listener with protocol `tcp`.

- `hosts` `(array<string>: nil)` - A list of hosts that specify what requests will
  match this service. This cannot be used with a `tcp` listener, and cannot be
  specified alongside a wildcard (`*`) service name. If not specified, the default
  domain `<service-name>.ingress.*` will be used to match services. Requests _must_
  send the correct host to be routed to the defined service.

  The wildcard specifier `*` can be used by itself to match all traffic coming to
  the ingress gateway, if TLS is not enabled. This allows a user to route all traffic
  to a single service without specifying a host, allowing simpler tests and demos.
  Otherwise, the wildcard specifier can be used as part of the host to match
  multiple hosts, but only in the leftmost DNS label. This ensures that all defined
  hosts are valid DNS records. For example, `*.example.com` is valid while `example.*`
  and `*-suffix.example.com` are not.

- `request_headers` `([header modifiers]: <optional>)` - A set of HTTP-specific
  header modification rules that will be applied to requests routed to this
  service. This cannot be used with a tcp listener.

- `response_headers` `([header modifiers]: <optional>)` - A set of HTTP-specific
  header modification rules that will be applied to responses from this
  service. This cannot be used with a tcp listener.

- `max_concurrent_requests` `(int: <optional>)` - Specifies the maximum number
  of concurrent HTTP/2 traffic requests that are allowed at a single point in
  time. If unset, will default to the Envoy proxy's default.

- `max_connections` `(int: <optional>)` - Specifies the maximum number of
  HTTP/1.1 connections a service instance is allowed to establish against the
  upstream. If unset, will default to the Envoy proxy's default.

- `max_pending_requests` `(int: <optional>)` - Specifies the maximum number of
  requests that are allowed to queue while waiting to establish a connection.
  If unset, will default to the Envoy proxy's default.

- `tls` <code>([tls]: nil)</code> - TLS configuration for this service.

#### Header modifier parameters

The `request_headers` and `response_headers` blocks of an `ingress.service`
block accept the following parameters. For more details, see the [Consul
documentation][response-headers].

- `add` `(map<string|string>: optional)` - A set of key-value pairs to add to the
  headers, where header names are keys and header values are the values. Header
  names are not case-sensitive. If header values with the same name already
  exist, the value is appended and Consul applies both headers.

- `set` `(map<string|string>: optional)` - A set of key-value pairs to add to the
  response header or to replace existing header values with. Use header names as
  the keys. Header names are not case-sensitive. If header values with the same
  names already exist, Consul replaces the header values.

- `remove` `array(string): optional` - Defines a list of headers to remove. Consul
  removes only headers containing exact matches. Header names are not
  case-sensitive.

#### `tls` parameters

- `enabled` `(bool: false)` - Set this configuration to enable TLS for every
  listener on the gateway. If TLS is enabled, then each host defined in the
  `host` field will be added as a DNSSAN to the gateway's x509 certificate.

- `cipher_suites` `(array<string>: optional)` - Set the default list of TLS
  cipher suites for the gateway's listeners. Refer to
  [`CipherSuites`](/consul/docs/connect/config-entries/ingress-gateway#ciphersuites)
  in the Consul documentation for the supported cipher suites.

- `sds` `(block: optional)` - Defines a set of parameters that configures the
  listener to load TLS certificates from an external Secret Discovery Service
  ([SDS][]).

  - `cluster_name` `(string)` - The SDS cluster name to connect to to retrieve
    certificates.

  - `cert_resource` `(string)` - The SDS resource name to request when fetching
    the certificate from the SDS service.

- `tls_max_version` `(string: optional)` - Set the default maximum TLS version
  supported by the gateway. Refer to
  [`TLSMaxVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsmaxversion)
  in the Consul documentation for supported versions.

- `tls_min_version` `(string: optional)` - Set the default minimum TLS version
  supported by the gateway. Refer to
  [`TLSMinVersion`](/consul/docs/connect/config-entries/ingress-gateway#tlsminversion)
  in the Consul documentation for supported versions.

### `terminating` parameters

- `service` <code>(array<[linked-service]>: required)</code> - One or more services to be
  linked with the gateway. The gateway will proxy traffic to these services. These
  linked services must be registered with Consul for the gateway to discover their
  addresses. They must also be registered in the same Consul datacenter as the
  terminating gateway.

#### linked `service` parameters

The `service` blocks for a `terminating` gateway accept the following
parameters. Note these are different than the `service` blocks for listeners
under an `ingress` gateway.

- `name` `(string: required)` - The name of the service to link with the
  gateway. If the wildcard specifier `*` is provided, then ALL services within
  the Consul namespace wil lbe linked with the gateway.

- `ca_file` `(string: <optional>)` - A file path to a PEM-encoded certificate
  authority. The file must be accessible by the gateway task. The certificate
  authority is used to verify the authenticity of the service linked with the
  gateway. It can be provided along with a `cert_file` and `key_file` for mutual
  TLS authentication, or on its own for one-way TLS authentication. If none is
  provided the gateway **will not** encrypt traffic to the destination.

- `cert_file` `(string: <optional>)` - A file path to a PEM-encoded certificate.
  The file must be accessible by the gateway task. The certificate is provided
  to servers to verify the gateway's authenticity. It must be provided if a
  `key_file` is provided.

- `key_file` `(string: <optional>)` - A file path to a PEM-encoded private key.
  The file must be accessible by the gateway task. The key is used with the
  certificate to verify the gateway's authenticity. It must be provided if a
  `cert_file` is provided.

- `sni` `(string: <optional>)` - An optional hostname or domain name to specify
  during the TLS handshake.

### `mesh` parameters

The `mesh` block currently does not have any configurable parameters.

~> **Note:** If using the Mesh Gateway for [WAN Federation][connect_mesh_gw],
the additional piece of service metadata `{"consul-wan-federation":"1"}` must
be applied. This can be done with the service [`meta`][meta] parameter.

## Gateway with host networking

Nomad supports running gateways using host networking. A static port must be allocated
for use by the [Envoy admin interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin)
and assigned to the proxy service definition.

!> **Warning:** There is no way to disable the Envoy admin interface, which will be
accessible to any workload running on the same Nomad client. The admin interface exposes
information about the proxy, including a Consul Service Identity token if Consul ACLs
are enabled.

## Specify Envoy image

The Docker image used for Connect gateway tasks defaults to the official [Envoy
Docker] image, `docker.io/envoyproxy/envoy:v${NOMAD_envoy_version}`, where `${NOMAD_envoy_version}`
is resolved automatically by a query to Consul. The image to use can be configured
by setting `meta.connect.gateway_image` in the Nomad job. Custom images can still
make use of the envoy version interpolation, e.g.

```hcl
meta.connect.gateway_image = custom/envoy-${NOMAD_envoy_version}:latest
```

## Custom gateway task

The task created for the gateway can be configured manually using the
[`sidecar_task`][sidecar_task] block.

```hcl
connect {
  gateway {
    # ...
  }

  sidecar_task {
    # see /docs/job-specification/sidecar_task for more details
  }
}
```

## Examples

### ingress gateway

```hcl
job "ingress-demo" {

  datacenters = ["dc1"]

  # This group will have a task providing the ingress gateway automatically
  # created by Nomad. The ingress gateway is based on the Envoy proxy being
  # managed by the docker driver.
  group "ingress-group" {

    network {
      mode = "bridge"

      # This example will enable plain HTTP traffic to access the uuid-api connect
      # native example service on port 8080.
      port "inbound" {
        static = 8080
        to     = 8080
      }
    }

    service {
      name = "my-ingress-service"
      port = "8080"

      connect {
        gateway {

          # Consul gateway [envoy] proxy options.
          proxy {
            # The following options are automatically set by Nomad if not
            # explicitly configured when using bridge networking.
            #
            # envoy_gateway_no_default_bind = true
            # envoy_gateway_bind_addresses "uuid-api" {
            #   address = "0.0.0.0"
            #   port    = <associated listener.port>
            # }
            #
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
          }

          # Consul Ingress Gateway Configuration Entry.
          ingress {
            # Nomad will automatically manage the Configuration Entry in Consul
            # given the parameters in the ingress block.
            #
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#ingress-parameters
            listener {
              port     = 8080
              protocol = "tcp"
              service {
                name = "uuid-api"
              }
            }
          }
        }
      }
    }
  }

  # The UUID generator from the connect-native demo is used as an example service.
  # The ingress gateway above makes access to the service possible over normal HTTP.
  # For example,
  #
  # $ curl $(dig +short @127.0.0.1 -p 8600 uuid-api.ingress.dc1.consul. ANY):8080
  group "generator" {
    network {
      mode = "host"
      port "api" {}
    }

    service {
      name = "uuid-api"
      port = "api"

      connect {
        native = true
      }
    }

    task "generate" {
      driver = "docker"

      config {
        image        = "hashicorpdev/uuid-api:v5"
        network_mode = "host"
      }

      env {
        BIND = "0.0.0.0"
        PORT = "${NOMAD_PORT_api}"
      }
    }
  }
}
```

### terminating gateway

```hcl
job "countdash-terminating" {

  datacenters = ["dc1"]

  # This group provides the service that exists outside of the Consul service mesh
  # . It is using host networking and listening to a statically
  # allocated port.
  group "api" {
    network {
      mode = "host"
      port "port" {
        static = "9001"
      }
    }

    # This example will enable services in the service mesh to make requests
    # to this service which is not in the service mesh by making requests
    # through the terminating gateway.
    service {
      name = "count-api"
      port = "port"
    }

    task "api" {
      driver = "docker"

      config {
        image        = "hashicorpdev/counter-api:v3"
        network_mode = "host"
      }
    }
  }

  group "gateway" {
    network {
      mode = "bridge"
    }

    service {
      name = "api-gateway"

      connect {
        gateway {
          # Consul gateway [envoy] proxy options.
          proxy {
            # The following options are automatically set by Nomad if not explicitly
            # configured with using bridge networking.
            #
            # envoy_gateway_no_default_bind = true
            # envoy_gateway_bind_addresses "default" {
            #   address = "0.0.0.0"
            #   port    = <generated listener port>
            # }
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
          }

          # Consul Terminating Gateway Configuration Entry.
          terminating {
            # Nomad will automatically manage the Configuration Entry in Consul
            # given the parameters in the terminating block.
            #
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#terminating-parameters
            service {
              name = "count-api"
            }
          }
        }
      }
    }
  }

  # The dashboard service is in the service mesh, making use of bridge network
  # mode and connect.sidecar_service. When running, the dashboard should be
  # available from a web browser at localhost:9002.
  group "dashboard" {
    network {
      mode = "bridge"

      port "http" {
        static = 9002
        to     = 9002
      }
    }

    service {
      name = "count-dashboard"
      port = "9002"

      connect {
        sidecar_service {
          proxy {
            upstreams {
              # By configuring an upstream destination to the linked service of
              # the terminating gateway, the dashboard is able to make requests
              # through the gateway to the count-api service.
              destination_name = "count-api"
              local_bind_port  = 8080
            }
          }
        }
      }
    }

    task "dashboard" {
      driver = "docker"

      env {
        COUNTING_SERVICE_URL = "http://${NOMAD_UPSTREAM_ADDR_count_api}"
      }

      config {
        image = "hashicorpdev/counter-dashboard:v3"
      }
    }
  }
}
```

### mesh gateway

Mesh gateways are useful when Connect services need to make cross-datacenter
requests where not all nodes in each datacenter have full connectivity. This example
demonstrates using mesh gateways to enable making requests between datacenters
`one` and `two`, where each mesh gateway will bind to the `public` host network
configured on at least one Nomad client in each datacenter.

Job running where Nomad and Consul are in datacenter `one`.

```hcl
job "countdash-mesh-one" {
  datacenters = ["one"]

  group "mesh-gateway-one" {
    network {
      mode = "bridge"

      # A mesh gateway will require a host_network configured on at least one
      # Nomad client that can establish cross-datacenter connections. Nomad will
      # automatically schedule the mesh gateway task on compatible Nomad clients.
      port "mesh_wan" {
        host_network = "public"
      }
    }

    service {
      name = "mesh-gateway"

      # The mesh gateway connect service should be configured to use a port from
      # the host_network capable of cross-datacenter connections.
      port = "mesh_wan"

      connect {
        gateway {
          mesh {
            # No configuration options in the mesh block.
          }

          # Consul gateway [envoy] proxy options.
          proxy {
            # The following options are automatically set by Nomad if not explicitly
            # configured with using bridge networking.
            #
            # envoy_gateway_no_default_bind = true
            # envoy_gateway_bind_addresses "lan" {
            #   address = "0.0.0.0"
            #   port    = <generated dynamic port>
            # }
            # envoy_gateway_bind_addresses "wan" {
            #   address = "0.0.0.0"
            #   port    = <configured service port>
            # }
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
          }
        }
      }
    }
  }

  group "dashboard" {
    network {
      mode = "bridge"

      port "http" {
        static = 9002
        to     = 9002
      }
    }

    service {
      name = "count-dashboard"
      port = "9002"

      connect {
        sidecar_service {
          proxy {
            upstreams {
              destination_name = "count-api"
              local_bind_port  = 8080

              # This dashboard service is running in datacenter "one", and will
              # make requests to the "count-api" service running in datacenter
              # "two", by going through the mesh gateway in each datacenter.
              datacenter       = "two"

              mesh_gateway {
                # Using "local" mode indicates requests should exit this datacenter
                # through the mesh gateway, and enter the destination datacenter
                # through a mesh gateway in that datacenter.
                # Using "remote" mode indicates requests should bypass the local
                # mesh gateway, instead directly connecting to the mesh gateway
                # in the destination datacenter.
                mode = "local"
              }
            }
          }
        }
      }
    }

    task "dashboard" {
      driver = "docker"

      env {
        COUNTING_SERVICE_URL = "http://${NOMAD_UPSTREAM_ADDR_count_api}"
      }

      config {
        image = "hashicorpdev/counter-dashboard:v3"
      }
    }
  }
}
```

Job running where Nomad and Consul are in datacenter `two`.

```hcl
job "countdash-mesh-two" {
  datacenters = ["two"]

  group "mesh-gateway-two" {
    network {
      mode = "bridge"

      # A mesh gateway will require a host_network configured for at least one
      # Nomad client that can establish cross-datacenter connections. Nomad will
      # automatically schedule the mesh gateway task on compatible Nomad clients.
      port "mesh_wan" {
        host_network = "public"
      }
    }

    service {
      name = "mesh-gateway"

      # The mesh gateway connect service should be configured to use a port from
      # the host_network capable of cross-datacenter connections.
      port = "mesh_wan"

      connect {
        gateway {
          mesh {
            # No configuration options in the mesh block.
          }

          # Consul gateway [envoy] proxy options.
          proxy {
            # The following options are automatically set by Nomad if not explicitly
            # configured with using bridge networking.
            #
            # envoy_gateway_no_default_bind = true
            # envoy_gateway_bind_addresses "lan" {
            #   address = "0.0.0.0"
            #   port    = <generated dynamic port>
            # }
            # envoy_gateway_bind_addresses "wan" {
            #   address = "0.0.0.0"
            #   port    = <configured service port>
            # }
            # Additional options are documented at
            # https://developer.hashicorp.com/nomad/docs/job-specification/gateway#proxy-parameters
          }
        }
      }
    }
  }

  group "api" {
    network {
      mode = "bridge"
    }

    service {
      name = "count-api"
      port = "9001"
      connect {
        sidecar_service {}
      }
    }

    task "api" {
      driver = "docker"

      config {
        image = "hashicorpdev/counter-api:v3"
      }
    }
  }
}
```


[address]: /nomad/docs/job-specification/gateway#address-parameters
[advanced configuration]: /consul/docs/connect/proxies/envoy#advanced-configuration
[connect_timeout_ms]: /consul/docs/connect/config-entries/service-resolver#connecttimeout
[connect_mesh_gw]: /consul/docs/connect/gateways/mesh-gateway/wan-federation-via-mesh-gateways#mesh-gateways
[envoy docker]: https://hub.docker.com/r/envoyproxy/envoy/tags
[ingress]: /nomad/docs/job-specification/gateway#ingress-parameters
[proxy]: /nomad/docs/job-specification/gateway#proxy-parameters
[linked-service]: /nomad/docs/job-specification/gateway#linked-service-parameters
[listener]: /nomad/docs/job-specification/gateway#listener-parameters
[interpolation]: /nomad/docs/reference/runtime-variable-interpolation
[listener-service]: /nomad/docs/job-specification/gateway#listener-service-parameters
[service-default]: /consul/docs/connect/config-entries/service-defaults
[sidecar_task]: /nomad/docs/job-specification/sidecar_task
[terminating]: /nomad/docs/job-specification/gateway#terminating-parameters
[tls]: /nomad/docs/job-specification/gateway#tls-parameters
[mesh]: /nomad/docs/job-specification/gateway#mesh-parameters
[meta]: /nomad/docs/job-specification/service#meta
[envoy_sd_docs]: https://www.envoyproxy.io/docs/envoy/v1.16.1/intro/arch_overview/upstream/service_discovery
[SDS]: https://developer.hashicorp.com/consul/docs/connect/config-entries/ingress-gateway#listeners-services-tls-sds
[service-default-protocol]: /consul/docs/connect/config-entries/service-defaults#protocol
[response-headers]: /consul/docs/connect/config-entries/ingress-gateway#listeners-services-responseheaders
[header modifiers]: /nomad/docs/job-specification/gateway#header-modifier-parameters
